<?php
/**
 * Created by PhpStorm.
 * User: guokunsheng
 * Date: 2020/9/2
 * Time: 19:09
 */

namespace app\web\controller;

use app\api\controller\v2\Auth;
use app\common\cachemodel\AppQq;
use app\common\cachemodel\AppSynastryResult;
use app\common\cachemodel\AppSynastryResult2021;
use app\common\cachemodel\Goods;
use app\common\cachemodel\Orders as OrdersModel;
use app\common\cachemodel\Recode as RecodeCacheModel;
use app\common\cachemodel\UserCoupon;
use app\common\cachemodel\Wechat;
use app\common\cachemodel\ZlRecordShareAdd;
use app\common\lib\Aes;
use app\common\lib\astrolog\Astrolog;
use app\common\lib\astrolog\SynastryData;
use app\common\lib\exception\ApiException;
use app\common\lib\IAuth;
use app\common\lib\Jssdk;
use app\common\lib\Push;
use app\common\lib\Util;
use app\common\model\MessageCenter;
use app\common\model\Recode;
use app\common\model\User;
use think\Controller;
use think\Env;
use think\Exception;
use think\Log;
use think\Request;
use think\response\Json;

/**
 * 合盘
 * Class Synastry
 * @package app\web\controller
 */
class Synastry extends Controller
{
    private $oss = '';
    private $domain = '';
    //微信分享图片
    protected $share_img = '';
    protected $LOG_PRE = '邀请合盘错误：';
    protected $noNeedJudgeSummer = ['香港特别行政区', '澳门特别行政区', '台湾省', '北美洲', '大洋洲', '非洲', '南美洲', '欧洲', '亚洲', ''];
    protected $isDebug = false;

    // 构造方法
    public function __construct(Request $request = null)
    {
        $this->oss = Env::get('host.photo');
        $this->domain = Env::get('host.domain');
        $this->share_img = $this->oss . 'web/invitate_input_record/images/share_logo.png';
        parent::__construct($request);
    }

    /**
     * 获取合盘结果
     */
    public function detail()
    {
        // 检查运行环境：true => 运行在APP内 , false => 在APP外的请求
        $rn = $this->checkRuntimeEnvironment();

        $record1 = [];
        // 明星档案信息
        $record2 = [
            'name' => '张新成',
            'avatar' => '/uploads/20200902/08c4b8749a5008493135677cd3607794.png',
            'type' => 1,
            'year' => 1995,
            'month' => 8,
            'day' => 24,
            'hour' => 6,
            'minute' => 12,
            'timezone' => 8,
            'birth_country' => '湖北省',
            'birth_province' => '荆州市',
            'birth_city' => '市辖区',
            'live_country' => '北京市',
            'live_province' => '北京市',
            'live_city' => '东城区',
            'long_deg' => 112,
            'long_min' => 14,
            'ew' => 1,
            'lat_deg' => 30,
            'lat_min' => 19,
            'ns' => 1,
            'is_summer' => 0,
        ];

        $token = input('token/s', '');
        if ($token != '')
        {
            $str = (new Aes())->decryptWithOpenssl(base64_decode($token));

            if (empty($str)) $this->error('参数错误');
            // 解析参数到档案1
            parse_str($str, $record1);
        }

        $data = [
            'oss' => Env::get('host.photo'),
        ];
        // 不是填写信息后进入的结果页面，未正确传递token加密参数
        if (empty($record1))
        {
            // 未在APP内使用明星合盘网页功能，前往填写档案信息界面
            if ($rn === false)
            {
                $data['title'] = '挖掘你与明星的隐藏缘分';
                // 设置档案默认值
                $data['record'] = [
                    'name' => '游客' . date('hms'),
                    'avatar' => Env::get('host.domain') . '/static/synastry/img/avatar-default.png',
                    'type' => 2,
                    'year' => 1995,
                    'month' => '01',
                    'day' => '01',
                    'hour' => '00',
                    'minute' => '00',
                    'timezone' => 8,
                    'birth_country' => '北京市',
                    'birth_province' => '北京市',
                    'birth_city' => '东城区',
                    'live_country' => '北京市',
                    'live_province' => '北京市',
                    'live_city' => '东城区',
                    'isself' => 0,
                    'long_deg' => 116,
                    'long_min' => 25,
                    'ew' => 1,
                    'lat_deg' => 39,
                    'lat_min' => 55,
                    'ns' => 1,
                    'is_summer' => 0,
                ];
                return $this->fetch('add', $data);
            }// 若在APP内，则开始获取用户自己的档案信息
            else
            {
                $auth = new Auth();
                $uid = (int)$auth->user['id'];
                // 开始获取当前用户档案信息
                $RecodeCacheModel = new RecodeCacheModel();
                // 获取用户自己的档案
                $record1 = $RecodeCacheModel->getRecodeLists($uid, 1);
            }
        }

        $options = [
            'recode1' => $record1,
            'recode2' => $record2,// 刚添加的档案
            'type' => 1,// 获取简易数据，只需要分数和最佳关系
        ];
        $synastryResult = (new SynastryData())->getScore($options);

        $synastryResult['nickname1'] = $record1['name'];
        $synastryResult['avatar1'] = $record1['avatar'];
        $synastryResult['nickname2'] = $record2['name'];
        $synastryResult['avatar2'] = $record2['avatar'];
        $data['result'] = $synastryResult;

        $data['total_score'] = $synastryResult['score']['attract']['num'] +
            $synastryResult['score']['chat']['num'] +
            $synastryResult['score']['passion']['num'] +
            $synastryResult['score']['benefit']['num'] +
            $synastryResult['score']['happy']['num'] +
            $synastryResult['score']['probTobeLover']['num'];

        return $this->fetch('whole_result', $data);
//        // 打开结果页面，APP内打开完整结果页面
//        if ($rn === true)
//        {
//            return $this->fetch('whole_result', $data);
//        }// APP外，则打开简洁版页面
//        else
//        {
//            return $this->fetch('simple_result', $data);
//        }
    }

    /**
     * 检测页面运行环境
     * 在APP内容使用时必须登录状态，且必须有自己的档案
     */
    protected function checkRuntimeEnvironment(): bool
    {
        // 首先需要获取headers
        $this->headers = $this->request->header();

        if (isset($this->headers['sign'])
            && strpos(config('app.app_types'), $this->headers['app-type']) !== true
            && IAuth::checkSignPass($this->headers))
        {
            return true;
        }

        return false;
    }

    public function getDetailsUrl()
    {
        $param = $this->request->param();

        $data = [
            'name' => htmlspecialchars(trim($param['name'])),
            'avatar' => $param['avatar'] ?? Env::get('host.domain') . '/static/synastry/img/avatar-default.png',
            'type' => (int)$param['sex'],
            'year' => (int)$param['year'],
            'month' => (int)$param['month'],
            'day' => (int)$param['day'],
            'hour' => (int)$param['hour'],
            'minute' => (int)$param['minute'],
            'birth_country' => htmlspecialchars(trim($param['birth_country'])),
            'birth_province' => htmlspecialchars(trim($param['birth_province'])),
            'birth_city' => htmlspecialchars(trim($param['birth_city'])),
//            'live_country' => htmlspecialchars(trim($param['live_country'])),
//            'live_province' => htmlspecialchars(trim($param['live_province'])),
//            'live_city' => htmlspecialchars(trim($param['live_city'])),
            'long_deg' => (int)$param['long_deg'],
            'long_min' => (int)$param['long_min'],
            'ew' => (int)$param['ew'],
            'lat_deg' => (int)$param['lat_deg'],
            'lat_min' => (int)$param['lat_min'],
            'ns' => (int)$param['ns'],
            'is_summer' => 0,
            'timezone' => 8
        ];
        $this->noNeedJudgeSummer = ['香港特别行政区', '澳门特别行政区', '台湾省', '北美洲', '大洋洲', '非洲', '南美洲', '欧洲', '亚洲', ''];

        // 只判断大陆地区的夏令时
        if (!in_array($data['birth_country'], $this->noNeedJudgeSummer, true))
        {
            $data['is_summer'] = isSummerTime($data['hour'], $data['minute'], 0, $data['month'], $data['day'], $data['year']) ? 1 : 0;// 是否开启夏令时
        }

        unset($data['birth_country'], $data['birth_province'], $data['birth_city']);

        $token = base64_encode(IAuth::setSign($data));

        $url = url('detail') . '?token=' . $token;

        return show(200, '请求成功', ['url' => $url]);
    }

    /**
     * 邀请添加合盘档案
     */
    public function add2023()
    {
        $token = input('token/s', '');
        // access-token AES解密
        if ($this->isDebug)
        {
            $str = 'uid=2&timestamp=' . time() . '&share_to=1';
            session('love.unionid', 'oIVMdtzIVRCFZPJU4x9lNZCG42d8');
            session('love.headimgurl', 'https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTI8WTXk7RbsqrtGH8OsYjvkpa3z6pDCicVxk4BvKnz5icrWrnNkH0SicNYpWmiaGIrjs7N9cATJY4tjrw/132');
            session('love.name', 'Seunk');
            session('qq.unionid', 'UID_9D945202BC4D87B85839847755DECA14');
            session('qq.headimgurl', 'http://thirdqq.qlogo.cn/g?b=oidb&k=cEaOXLIFWIu5lH9AMfo8pg&s=40&t=1556668773');
            session('qq.name', 'Seunk');
        } else
        {
            $str = (new Aes())->decryptWithOpenssl(base64_decode($token));
        }
        if (empty($str))
        {
            throw new ApiException($this->LOG_PRE . '参数错误');
        }
        parse_str($str, $params);
        //检查输入参数是否正确
        if (!isset($params['uid']))
        {
            throw new ApiException($this->LOG_PRE . 'uid参数为空');
        }
        if (!isset($params['timestamp']))
        {
            throw new ApiException($this->LOG_PRE . 'timestamp参数为空');
        }
        if (!isset($params['share_to']))
        {
            throw new ApiException($this->LOG_PRE . 'share_to参数为空');
        }
        if ($params['share_to'] * 1 !== 1 && $params['share_to'] * 1 !== 2)
        {
            throw new ApiException($this->LOG_PRE . 'share_to参数错误，只能为【1：微信；2：qq】，实际为' . $params['share_to']);
        }
        //检查session，如果不存在，那么就直接跳转到登录
        $this->checkLogin2023($token, $params['share_to']);
        try
        {
            $record = [
                'uid' => '',
                'name' => '',
                'sex' => '',
                'year' => '',
                'month' => '',
                'day' => '',
                'hour' => '',
                'minute' => '',
                'timezone' => '',
                'birth_country' => '',
                'birth_province' => '',
                'birth_city' => '',
                'live_country' => '',
                'live_province' => '',
                'live_city' => '',
                'comments' => '',
                'isself' => '',
                'long_deg' => '',
                'long_min' => '',
                'ew' => '',
                'lat_deg' => '',
                'lat_min' => '',
                'ns' => '',
                'avatar' => '',
            ];
            $is_user_have_record = 0;
            $signPackage = [];

            $session_avatar = session('qq.headimgurl');
            $session_sex = session('qq.sex');
            $session_name = session('qq.name');
            $session_unionid = session('qq.unionid');
            if (1 === $params['share_to'] * 1)
            {
                $session_avatar = session('love.headimgurl');
                $session_sex = session('love.sex');
                $session_name = session('love.name');
                $session_unionid = session('love.unionid');
            }

            $data = [
                'uid' => $params['uid'],//用户id
                'status' => 0,//0：填写信息；1：已填写；2：提交成功；3：自己邀请自己，提示错误；4：请从qq或者微信打开；【这里只能输入1/2】
                'is_user_have_record' => 0,//根据unionid查询这个用户是否已经存在档案
                'inviter_name' => '',//邀请者的名字
                'share_to' => $params['share_to'],//【1：微信；2：qq】
                'signPackage' => $signPackage,//微信签名
                'unionid' => $session_unionid,
                'timestamp' => $params['timestamp'],
                'record' => $record
            ];

            $AppWechat = new Wechat();
            $AppQq = new AppQq();
            $Record = new Recode();
            $utilModel = new Util();

            //查询邀请者的名字
            $inviter = (new User())->getUserinfo(['id' => $params['uid']]);
            $inviter_name = $inviter['nickname'];
            $inviter_avatar = Util::getImgUrl($inviter['avatar']);
            $inviterRid = (int)$inviter['rid'];

            if (!$inviterRid)
            {   // 发送邀请用户 档案已删除
                $data['status'] = 5; // 链接失效
                return $this->fetch('add2023', [
                    'title' => '填写你的星盘配置',//网页标题
                    'share_title' => '快来看看我们的合盘关系解密',//微信分享标题. 填写你的星盘配置
                    'share_introduction' => '准了关系合盘，帮你看懂星盘中两人关系走向发展',//微信分享内容 一起刷新合盘榜，来拿恋爱报告！
                    'share_img' => $this->share_img,
                    'signPackage' => $signPackage,//微信签名
                    'data' => $data,//带过去的数据
                    'oss' => $this->oss,
                    'domain' => $this->domain,
                ]);
            }

            $inviterRecodeInfo = (new \app\common\cachemodel\Recode())->getInfoById($inviterRid, ['sun', 'moon', 'asc']);
            if ($inviterRecodeInfo)
            {
                $inviterRecodeDes = '日' . $utilModel->recodeAstroShorthand($inviterRecodeInfo['sun']) . '·月' . $utilModel->recodeAstroShorthand($inviterRecodeInfo['moon']) . '·升' . $utilModel->recodeAstroShorthand($inviterRecodeInfo['asc']);
            }

            //查询是邀请者自己点击进入的邀请h5，那么就直接提示错误
            if (1 === $params['share_to'] * 1)
            {
                //微信登录
                $wechat_info = $AppWechat->getWechatInfo($params['uid'], 2);
                if ($wechat_info && isset($wechat_info['unionid']) && $wechat_info['unionid'] === $session_unionid)
                {
                    //用户绑定了微信，自己邀请了自己
                    $data['status'] = 3;
                }
            } else
            {
                //qq登录
                $qq_info = $AppQq->getUserQqInfoFromCache($params['uid'], 2);
                if ($qq_info && isset($qq_info['unionid']) && $qq_info['unionid'] === $session_unionid)
                {
                    //用户绑定了qq，自己邀请了自己
                    $data['status'] = 3;
                }
            }
            $data['inviter_name'] = $inviter_name;//邀请者的名字
            $data['inviter_avatar'] = $inviter_avatar;//邀请者的头像
            $data['inviter_des'] = $inviterRecodeDes ?? '';//邀请者的 日月升 信息

            if ($data['status'] === 3)
            {   // 自己查看
                return $this->fetch('add2023', [
                    'title' => '填写你的星盘配置',//网页标题
                    'share_title' => '快来看看我们的合盘关系解密',//微信分享标题. 填写你的星盘配置
                    'share_introduction' => '准了关系合盘，帮你看懂星盘中两人关系走向发展',//微信分享内容 一起刷新合盘榜，来拿恋爱报告！
                    'share_img' => $this->share_img,
                    'signPackage' => $signPackage,//微信签名
                    'data' => $data,//带过去的数据
                    'oss' => $this->oss,
                    'domain' => $this->domain,
                ]);
            }

            //  被邀请者
            $ZlRecordShareAdd = new ZlRecordShareAdd();
            $shareId = $ZlRecordShareAdd
                ->where('type', $params['share_to'])
                ->where('code', $session_unionid)
                ->where('time', $params['timestamp'])
                ->value('id');

            if ($shareId)
            {
                //查到了这个用户，需要提示用户已经填写过了
                $status = 1;

                try
                {
                    $result = (new AppSynastryResult())->field('id,avatar1,avatar2,extra')
                        ->where('share_id', $shareId)
                        ->findOrFail()
                        ->toArray();
                }
                catch (\Exception $e)
                {
                    $data['status'] = 5;    // 链接失效
                    return $this->fetch('add2023', [
                        'title' => '填写你的星盘配置',//网页标题
                        'share_title' => '快来看看我们的合盘关系解密',//微信分享标题. 填写你的星盘配置
                        'share_introduction' => '准了关系合盘，帮你看懂星盘中两人关系走向发展',//微信分享内容 一起刷新合盘榜，来拿恋爱报告！
                        'share_img' => $this->share_img,
                        'signPackage' => $signPackage,//微信签名
                        'data' => $data,//带过去的数据
                        'oss' => $this->oss,
                        'domain' => $this->domain,
                    ]);
                }

                $extraData = isset($result['extra']) && $result['extra'] ? json_decode($result['extra'], true) : [];

                $record = $extraData['recode2'];
                $record['avatar'] = $result['avatar2'];
                // 更新用户旧数据
                $inviter_name = $extraData['recode1']['name'];
                $inviter_avatar = Util::getImgUrl($result['avatar1']);
                $inviterRecodeDes = '日' . $utilModel->recodeAstroShorthand($extraData['recode1']['sun']) . '·月' . $utilModel->recodeAstroShorthand($extraData['recode1']['moon']) . '·升' . $utilModel->recodeAstroShorthand($extraData['recode1']['asc']);

                $resultId = $result['id'];
            } else
            {
                //没有查到这个用户，需要用户填写
                $status = 0;
            }
            //根据unionid查询这个用户，是否微信/qq注册过
            if (1 === $params['share_to'] * 1)
            {
                //微信登录
                $appWechat = $AppWechat->getWechatInfo($session_unionid, 1);
                if (isset($appWechat['uid']))
                {
                    //查询这个用户是否有自己的档案
                    $recordTemp = $Record->getSelfRecode($appWechat);
                    if ($recordTemp)
                    {
                        if (empty($record) || !isset($record['year']) || $record['year'] === '')
                        {
                            $record = $recordTemp;
                        }
                        $is_user_have_record = 1;
                    }
                }
            } else
            {
                //qq登录
                $appQq = $AppQq->getUserQqInfoFromCache($session_unionid);
                if (isset($appQq['uid']))
                {
                    $recordTemp = $Record->getSelfRecode($appQq);
                    if ($recordTemp)
                    {
                        if (empty($record) || !isset($record['year']) || $record['year'] === '')
                        {
                            $record = $recordTemp;
                        }
                        $is_user_have_record = 1;
                    }
                }
            }
            //---数据处理---
            //替换type为sex
            if (isset($record['type']))
            {
                $record['sex'] = $record['type'];
            }
            if (isset($record['avatar']))
            {
                $record['avatar'] = Util::getImgUrl($record['avatar']);
            }
            //---数据处理---
            $data = [
                'uid' => $params['uid'],//用户id
                'status' => $status,//0：填写信息；1：已填写；已提交；3：自己邀请自己，提示错误；4：请从qq或者微信打开；【这里只能输入1/2】 5=>链接失效
                'record' => $record,
                'is_user_have_record' => $is_user_have_record,//根据unionid查询这个用户是否已经存在档案
                'inviter_name' => $inviter_name,//邀请者的名字
                'inviter_avatar' => $inviter_avatar,//邀请者的头像
                'inviter_des' => $inviterRecodeDes ?? '',//邀请者的 日月升 信息
                'share_to' => $params['share_to'],//【1：微信；2：qq】
                'unionid' => $session_unionid,
                'timestamp' => $params['timestamp'],
                'result_id' => $resultId ?? 0,//  为 合盘记录ID
                'token' => base64_encode(IAuth::setSign(['uid' => $params['uid'], 'timestamp' => time(), 'show_type' => 2])),
            ];

            if (!$is_user_have_record)
            {//如果用户没有档案，那么就把头像、昵称、性别传过去
                $data['record']['avatar'] = $session_avatar;
                $data['record']['sex'] = $session_sex;
                $data['record']['name'] = $session_name;
            } else
            {
                try
                {
                    //如果用户有档案，获取用户的现居地和出生地，省市区的code
                    $locations = Astrolog::getInstance()->getLocations();
                    $item = $locations[$data['record']['birth_country'] . '-' . $data['record']['birth_province'] . '-' . $data['record']['birth_city']];
                    $data['record']['code_birth_country'] = $item['code_country'];
                    $data['record']['code_birth_province'] = $item['code_province'];
                    $data['record']['code_birth_city'] = $item['code_city'];

                    $item = $locations[$data['record']['live_country'] . '-' . $data['record']['live_province'] . '-' . $data['record']['live_city']];
                    $data['record']['code_live_country'] = $item['code_country'];
                    $data['record']['code_live_province'] = $item['code_province'];
                    $data['record']['code_live_city'] = $item['code_city'];
                }
                catch (\Exception $e)
                {
                    //用户有档案，但是【获取用户的现居地和出生地，省市区的code】出错
                    $data['record']['avatar'] = $session_avatar;
                    $data['record']['sex'] = $session_sex;
                    $data['record']['name'] = $session_name;
                }
            }
            if (1 === $params['share_to'] * 1)
            {
                //微信分享的获取微信js签名
                $signPackage = (new Jssdk())->getSignPackage();
            }

            //时间小于10，加0补充
            $data['record']['month'] = str_pad($data['record']['month'], 2, '0', STR_PAD_LEFT);
            $data['record']['day'] = str_pad($data['record']['day'], 2, '0', STR_PAD_LEFT);
            $data['record']['hour'] = str_pad($data['record']['hour'], 2, '0', STR_PAD_LEFT);
            $data['record']['minute'] = str_pad($data['record']['minute'], 2, '0', STR_PAD_LEFT);

            return $this->fetch('add2023', [
                'title' => '填写你的星盘配置',//网页标题
                'share_title' => '快来看看我们的合盘关系解密',//微信分享标题. 填写你的星盘配置
                'share_introduction' => '准了关系合盘，帮你看懂星盘中两人关系走向发展',//微信分享内容 一起刷新合盘榜，来拿恋爱报告！
                'share_img' => $this->share_img,
                'signPackage' => $signPackage,//微信签名
                'data' => $data,//带过去的数据
                'oss' => $this->oss,
                'domain' => $this->domain,
            ]);
        }
        catch (\Exception $e)
        {
            throw new ApiException('[' . $e->getFile() . ':' . $e->getLine() . ']' . PHP_EOL . $this->LOG_PRE . '：[uid=' . $params['uid'] . '&timestamp=' . $params['timestamp'] . '&share_to=' . $params['share_to'] . ']' . $e->getMessage());
        }
    }

    /**
     * 档案信息保存
     * @return Json
     */
    public function saveRecord2023(): Json
    {
        //根据unionid查询这个用户是否已经存在档案；0：不存在；1：已存在；
        $is_user_have_record = input('is_user_have_record/d');
        $share_to = input('share_to/d');
        $timestamp = input('timestamp/d');
        $unionid = input('unionid/s', '', 'htmlspecialchars');// 档案名称;
        $uid = input('uid/d');//用户的id，此处是邀请者

        //检查输入参数是否正确
        if (empty($uid))
        {
            return show(config('code.error'), 'uid参数为空');
        }
        if (empty($timestamp))
        {
            return show(config('code.error'), 'timestamp参数为空');
        }
        if (empty($unionid))
        {
            return show(config('code.error'), 'unionid参数为空');
        }
        if (empty($share_to))
        {
            return show(config('code.error'), 'share_to参数为空');
        }
        if ($share_to * 1 !== 1 && $share_to * 1 !== 2)
        {
            return show(config('code.error'), 'share_to参数错误');
        }

        // 档案标签如 自己 朋友 案例
        $isself = 0;//input('isself/d');// 档案是否为自己 0 否 | 1 是（自己的档案无法删除，无法更改为其他标签）
        $comments = '朋友';//标签，默认为朋友

        $name = input('name/s', '', 'htmlspecialchars');// 档案名称
        $type = input('sex/d', 1);// 档案类型  1男 | 2 女 | 3 男同 | 4 女同 | 5 事件 | 6 卜卦
        if (!$type)
        {
            return show(config('code.error'), '请选择性别！');
        }
        if (!in_array($type, [1, 2, 3, 4, 5, 6], true))
        {
            return show(config('code.error'), '性别异常，请重新选择性别');
        }
        $year = input('year/d');// 出生时间-年
        $month = input('month/d');// 出生时间-月
        $day = input('day/d');// 出生时间-日
        $hour = input('hour/d');// 出生时间-时
        $minute = input('minute/d');// 出生时间-分
        $timezone = input('timezone/d', 8);// 出生时间-时区
        $birth_country = input('birth_country/s', '', 'htmlspecialchars');// 出生地点-省
        $birth_province = input('birth_province/s', '', 'htmlspecialchars');// 出生地点-市
        $birth_city = input('birth_city/s', '', 'htmlspecialchars');// 出生地点-区
        $live_country = input('live_country/s', '', 'htmlspecialchars');// 现居地-省
        $live_province = input('live_province/s', '', 'htmlspecialchars');// 现居地-省
        $live_city = input('live_city/s', '', 'htmlspecialchars');// 现居地-省
        $long_deg = input('long_deg/d');// 经度-度
        $long_min = input('long_min/d');// 经度-分
        $ew = input('ew/d');// 东经|西经 1|-1
        $lat_deg = input('lat_deg/d');// 纬度-度
        $lat_min = input('lat_min/d');// 纬度-分
        $ns = input('ns/d');// 南纬北纬  1|-1
        $avatar = input('avatar/s', '', 'htmlspecialchars_decode');// 头像地址

        $is_summer = 0;
        // 只判断大陆地区的夏令时
        if (!in_array($birth_country, $this->noNeedJudgeSummer, true))
        {
            $is_summer = isSummerTime($hour, $minute, 0, $month, $day, $year) ? 1 : 0;// 是否开启夏令时
        }

        $data = [
            'name' => $name,
            'type' => $type,
            'year' => $year,
            'month' => $month,
            'day' => $day,
            'hour' => $hour,
            'minute' => $minute,
            'timezone' => $timezone,
            'birth_country' => $birth_country,
            'birth_province' => $birth_province,
            'birth_city' => $birth_city,
            'live_country' => $live_country,
            'live_province' => $live_province,
            'live_city' => $live_city,
            'comments' => $comments,
            'isself' => $isself,
            'long_deg' => $long_deg,
            'long_min' => $long_min,
            'ew' => $ew,
            'lat_deg' => $lat_deg,
            'lat_min' => $lat_min,
            'ns' => $ns,
            'avatar' => $avatar,
            'is_summer' => $is_summer,
        ];
        $validate = validate('Recode');

        if (!$validate->scene('add')->check($data))
        {
            return show(config('code.error'), (string)$validate->getError());
        }
        try
        {
            if (!$is_user_have_record)
            {//头像是被邀请者，微信/qq授权获取的，需要上传到oss
                $avatarInfo = Util::wxImgUploadOss($avatar, 'uploads/avatar');
                $avatar = $avatarInfo['success'] ? $avatarInfo['url'] : $avatar;
                $data['avatar'] = $avatar;
            }
            // 替换掉oss域名
            $data['avatar'] = str_replace($this->oss, '', $data['avatar']);

            $record_share_add = [
                'uid' => $uid,
                'rid' => 0,
//            'name' => $name, // 没有，用户使用第三方登录的时候，再去获取
                'type' => $share_to,
                'sex' => $type,
                'code' => $unionid,
                'time' => $timestamp,
                'year' => $year,
                'month' => $month,
                'day' => $day,
                'hour' => $hour,
                'minute' => $minute,
//            'timezone' => $timezone, 这里默认都是8
                'birth_country' => $birth_country,
                'birth_province' => $birth_province,
                'birth_city' => $birth_city,
                'live_country' => $live_country,
                'live_province' => $live_province,
                'live_city' => $live_city,
//            'comments' => $comments,
//            'isself' => $isself,
                'long_deg' => $long_deg,
                'long_min' => $long_min,
                'ew' => $ew,
                'lat_deg' => $lat_deg,
                'lat_min' => $lat_min,
                'ns' => $ns,
                'create_time' => $this->request->time()
//            'avatar' => $avatar, //没有，用户使用第三方登录的时候，再去获取
//            'is_summer' => $is_summer,
            ];
            $ZlRecordShareAdd = new ZlRecordShareAdd();
            $shareId = $ZlRecordShareAdd->SaveData($record_share_add);
        }
        catch (\Exception $e)
        {
            Log::error('[' . $e->getFile() . ':' . $e->getLine() . ']' . PHP_EOL . $this->LOG_PRE . $e->getMessage() . PHP_EOL);
            return show(config('code.error'), '服务异常，请稍后重试！');
        }

        try
        {
            $AppSynastryResultModel = new AppSynastryResult();
            // 获取合盘关系与分数 并入库 更新排行榜
            $RecodeCacheModel = new RecodeCacheModel();
            // 获取用户自己的档案
            $orginSelfRecode = $RecodeCacheModel->getRecodeLists($uid, 1);
            $options = [
                'recode1' => $orginSelfRecode,
                'recode2' => $data,// 刚添加的档案
                'type' => 0,// 获取简易数据，只需要分数和最佳关系
            ];
            $synastryResult = (new SynastryData())->getScore($options);

            $synastryResultInsertData = [
                'uid' => $uid,
                'type' => 6,
                'create_type' => 1,
                'score' => $synastryResult['scoreNum'],
                'share_id' => $shareId,
                'create_time' => $this->request->time(),
                'update_time' => $this->request->time(),
                'rid1' => $orginSelfRecode['id'],
                'nickname1' => $orginSelfRecode['name'],
                'nickname2' => $data['name'],
                'avatar1' => $orginSelfRecode['avatar'],
                'avatar2' => $data['avatar'],
                'relation' => $synastryResult['relationText'],
                'extra' => json_encode([
                    'recode1' => $orginSelfRecode,
                    'recode2' => $data
                ]),
            ];

            $resultId = $AppSynastryResultModel->saveData($synastryResultInsertData);
        }
        catch (\Exception $e)
        {
            Log::error('[' . $e->getFile() . ':' . $e->getLine() . ']' . PHP_EOL . $this->LOG_PRE . $e->getMessage() . PHP_EOL);
            return show(config('code.error'), '服务异常，请稍后重试！');
        }

        // 消息中心添加信息
        $messageData = [
            'status' => 0,
            'is_read' => 0,
            'range' => $uid,
            'type' => 2,
            'reid' => 0,
            'cid' => 0,
            'title' => '邀请好友合盘成功',
            'content' => '点击查看与好友的合盘结果',
            'target' => 'local',
            'link' => 'composite',
            'create_time' => $this->request->time()
        ];
        //发送消息
        try
        {
            (new Push())->pushUserMsg($uid, $messageData['content'], ['action' => 'extend', 'target' => 'local', 'link' => 'composite'], $messageData['title']);
            //消息中心增加消息
            (new MessageCenter())->pushMessage($uid, $messageData);
        }
        catch (Exception $e)
        {
            Log::write($this->LOG_PRE . $e->getMessage() . ' [' . $e->getFile() . ':' . $e->getLine() . ']' . PHP_EOL, 'error', true);
        }
        //查询邀请者的名字
        return show(config('code.success'), '加载成功', [
            'id' => $resultId,
            'token' => base64_encode(IAuth::setSign(['uid' => $uid, 'timestamp' => time(), 'show_type' => 2])),
        ]);
    }

    /**
     * 微信登陆
     */
    public function weixin_login2023(): void
    {
        $token = input('get.token/s');
        $appid = config('wechat.mp_appid');

        $redirect_uri = urlencode($this->domain . '/web/synastry/weixin_back2023');
        header('location:https://open.weixin.qq.com/connect/oauth2/authorize?appid=' . $appid . '&redirect_uri=' . $redirect_uri . '&response_type=code&scope=snsapi_userinfo&state=' . $token . '#wechat_redirect');
        exit;
    }

    /**
     * 微信登陆返回
     */
    public function weixin_back2023(): void
    {
        $wechat_conf = config('wechat');
        $appid = $wechat_conf['mp_appid'];
        $appsecret = $wechat_conf['mp_secret'];

        $code = input('get.code/s');
        if (empty($code))
        {
            $this->error('微信授权失败！');
        }

        $token = input('get.state/s');
        if (empty($token))
        {
            $this->error('获取token失败！');
        }
        $access_token = session('love.access_token');
        if (empty($access_token) || $access_token === '')
        {
            $access_token_url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $appid . '&secret=' . $appsecret . '&code=' . $code . '&grant_type=authorization_code';
            $access_token = json_decode(file_get_contents($access_token_url), false);
            if (isset($access_token->errcode))
            {
                $this->error('授权失败');
            }
            session('love.access_token', $access_token->access_token);
            session('love.refresh_token', $access_token->refresh_token);
            session('love.openid', $access_token->openid);
        }

        $user_info_url = 'https://api.weixin.qq.com/sns/userinfo?access_token=' . session('love.access_token') . '&openid=' . session('love.openid') . '&lang=zh_CN';
        $user_info = json_decode(file_get_contents($user_info_url), false);
        if (isset($user_info->errcode))
        {
            $access_token_url = 'https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=' . $appid . '&grant_type=refresh_token&refresh_token=' . session('love.refresh_token');
            $access_token = json_decode(file_get_contents($access_token_url), true);
            if (isset($access_token['access_token'], $access_token['refresh_token'], $access_token['openid']) && !empty($access_token))
            {
                session('love.access_token', $access_token['access_token']);
                session('love.refresh_token', $access_token['refresh_token']);
                session('love.openid', $access_token['openid']);

                $user_info_url = 'https://api.weixin.qq.com/sns/userinfo?access_token=' . $access_token['access_token'] . '&openid=' . $access_token['openid'] . '&lang=zh_CN';
                $user_info = json_decode(file_get_contents($user_info_url), false);
                if (isset($user_info->errcode))
                {
                    echo '<h1>错误：</h1>' . $user_info->errcode;
                    echo '<br/><h2>错误信息：</h2>' . $user_info->errmsg;
                    exit;
                }
            } else
            {//失败的话，重新授权登录
                if (40001 === $user_info->errcode)
                {//40001为invalid credential, access_token is invalid or not latest, hints: [ req_id: EfKfY24ce-3ItL5 ]，清空access_token
                    session('love.access_token', null);
                }
                $this->redirect('/web/synastry/weixin_login?token=' . $token . '&zhunle_not_show_nav=1&zhunle_nav_text_color=1');
            }
        }
        //把unionid、headimgurl、name 保存到session里
        session('love.unionid', $user_info->unionid);
        session('love.headimgurl', $user_info->headimgurl);
        session('love.name', $user_info->nickname);
        session('love.sex', $user_info->sex);

        $this->redirect('/web/synastry/add2023?token=' . $token . '&zhunle_not_show_nav=1&zhunle_nav_text_color=1');
    }

    /**
     * 检查session里是否有  unionid、headimgurl、name 这三个参数，如果为空，那么跳转到 微信 或者 qq 登录页面
     * @param string $token app邀请档案传过来的加密数据
     * @param int $share_to 【1：微信；2：qq】
     */
    private function checkLogin2023($token = '', $share_to = 1): void
    {
        if (1 === $share_to * 1 &&
            (empty(session('love.unionid'))
                || empty(session('love.headimgurl'))
                || empty(session('love.name'))))
        {
            $this->redirect('/web/synastry/weixin_login2023?token=' . $token . '&zhunle_not_show_nav=1&zhunle_nav_text_color=1');
        } else if (2 === $share_to * 1 &&
            (empty(session('qq.unionid'))
                || empty(session('qq.headimgurl'))
                || empty(session('qq.name'))))
        {
            $this->redirect('/web/synastry/qq_login2023?token=' . $token . '&zhunle_not_show_nav=1&zhunle_nav_text_color=1');
        }
    }

    /**
     * qq登录
     */
    public function qq_login2023(): void
    {
        //APP ID：101831016
        //APP Key：0d7d3ce6619c9b3306a8d01386384198
        $app_id = '101831016';
        $app_secret = '0d7d3ce6619c9b3306a8d01386384198';
        $my_url = $this->domain . '/web/synastry/qq_login2023';

        //注  回调地址必须和该代码域名一致
        if (empty($_GET['code']))
        {//判断是否有code,若无code则去qq第三方接口请求授权
//            $_SESSION['state'] = md5(uniqid(rand(), true));//一串随机的字符串，用于回调时对比参数防止csrf攻击
            //拼接url地址同时url化回调地址并跳转
            $token = input('get.token/s');
            $url = 'https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=' . $app_id . '&redirect_uri=' . urlencode($my_url) . '&state=' . $token;
            header('location: ' . $url);
        } else
        {
            $token = input('get.state/s');
            //省略一步  使用state判断是否csrf攻击   使用$_SESSION['state']和$_GET['state']进行对比判断授权过程是否被劫持
            //拼接url地址使用code请求并获得access_token
            $url = 'https://graph.qq.com/oauth2.0/token?grant_type=authorization_code&client_id=' . $app_id . '&client_secret='
                . $app_secret . '&code=' . $_GET['code'] . '&redirect_uri=' . $my_url;
            //发出请求
            $info = file_get_contents($url);
            //var_dump($info);由于传回来的数据是个字符串，不能直接使用，所以进行变量化
            $params = [];
            parse_str($info, $params);//把传回来的数据参数变量化
            //var_dump($params);变量化后的结果
            /*
             * array(3) {
             *  ["access_token"]=> string(32) "*********"  access_token
             *  ["expires_in"]=> string(7) "7776000"    access_token有效时间
             * ["refresh_token"]=> string(32) "****" }
             * */
            //判断access_token是否存在，如果不存在，那么让用户重新获取，例如：{"error":100019,"error_description":"code to access token error"}
            if (!isset($params['access_token']))
            {
                $this->redirect('/web/synastry/add2023?token=' . $token . '&zhunle_not_show_nav=1&zhunle_nav_text_color=1');
            }

            //使用access_token去请求openid
            $graph_url = 'https://graph.qq.com/oauth2.0/me?access_token=' . $params['access_token'] . '&unionid=1';
            $str = file_get_contents($graph_url);
            //var_dump($str);  请求得到的结果
            //string(83) "callback( {"client_id":"*****","openid":"*****"} ); "
            //callback( {"client_id":"101255228","openid":"89F5D3BB8CEE2B386B02EAC397270E46","unionid":"UID_F3EEF816AB02F7B33521E87A5118B6FA"} );
            //由于得到的结果还是字符串且还不是json类型，只能手动截取json格式的数据
            //判断callback在字符串$str是否存在，如果存在则返回下标，否则false，下标不完全等于false，因为0会被判断为false
            if (strpos($str, 'callback') !== false)
            {
                $lpos = strpos($str, '(');//判断(出现的下标
                $rpos = strrpos($str, ')');//判断)出现的下标，加上r从右边开始查找
                $str = substr($str, $lpos + 1, $rpos - $lpos - 1);//截取字符串
                //从$rpos+1下标 { 处截取  $rpos - $lpos -1 位 ，此时$str的值就为一个json格式的数据了
                // {"client_id":"*****","openid":"*****"}
            }
            $user = json_decode($str, true);//json转对象,存放有返回的数据 client_id ，openid
            //拼接url并访问，用access_token和openid得到用户信息
            $urls = 'https://graph.qq.com/user/get_user_info?access_token=' . $params['access_token'] . '&oauth_consumer_key=' . $app_id . '&openid=' . $user['openid'];
            $rs = file_get_contents($urls);
            $ref = json_decode($rs, true);//得到的用户信息

            //把unionid、headimgurl、name 保存到session里
            session('qq.unionid', $user['unionid']);
            session('qq.headimgurl', $ref['figureurl_qq_1']);
            session('qq.name', $ref['nickname']);
            session('qq.sex', $ref['gender_type']);

            $this->redirect('/web/synastry/add2023?token=' . $token . '&zhunle_not_show_nav=1&zhunle_nav_text_color=1');
        }
    }

    /**
     * 合盘结果页
     */
    public function get_with_score2023()
    {
        $id = input('id/d', 0);
        $shareId = input('share_id/d', 0);

        if (!$id && !$shareId)
        {
            throw new ApiException($this->LOG_PRE . '参数错误1');
        }
        $token = input('token/s', '');
        // token AES解密
        $str = (new Aes())->decryptWithOpenssl(base64_decode($token));

        if (empty($str) || strpos($str, 'uid=') === false)
        {
            throw new ApiException($this->LOG_PRE . '参数错误2');
        }

        parse_str($str, $params);

        if (empty($params) || !isset($params['uid']) || !$params['uid'])
        {
            throw new ApiException($this->LOG_PRE . '参数错误3');
        }

        try
        {
            $where = $id ? ['id' => $id] : ['share_id' => $shareId];
            $result = (new AppSynastryResult())->field('uid,nickname1,nickname2,avatar1,avatar2,extra')
                ->where($where)
                ->findOrFail()
                ->toArray();

            $result['avatar1'] = Util::getImgUrl($result['avatar1']);
            $result['avatar2'] = Util::getImgUrl($result['avatar2']);
        }
        catch (\Exception $e)
        {
            throw new ApiException($this->LOG_PRE . '未知合盘');
        }

        $records = json_decode($result['extra'], true);
        // 获取完整合盘数据
        $records['type'] = 1;

        $data = (new SynastryData())->getScore($records);

        $score = 0;
        foreach ($data['score'] as $item)
        {
            $score += $item['num'];
        }
        // 区分完整版和简易引导版的展示
        $showType = (isset($params['show_type']) && $params['show_type'] != 2) ? 'get_with_score2023' : 'simple_result2023';
        $tips = '';
        if ($showType === 'simple_result2023')
        {
            /**
             * 5-300分    85%-90%
             * 300-400分    90%-95%
             * 400-500分     96%-98%
             * 500分以上    99%
             */
            if ($score >= 500)
            {
                $per = 99;
            } elseif ($score >= 400)
            {
                $per = random_int(96, 98);
            } elseif ($score >= 300)
            {
                $per = random_int(91, 95);
            } else
            {
                $per = random_int(85, 90);
            }
            $tips = '你与Ta的合盘分数打败了' . $per . '%的用户';
        }

        // 合盘结果分享文案
        if ($score < 300)
        {
            $shareTitle = '七夕来合盘！这个合盘分析太准了！';
            $shareDes = '我俩要继续狗望狗了';
        } else
        {
            $shareTitle = '奔走相告！这个七夕找到和我最合的人了！';
            $shareDes = '决定手牵手了！';
        }

        $app_type = $this->request->header('app-type', '');

        $unlockNum1 = 0;
        if ($params['show_type'] == 3)
        {
            $orderModel = new OrdersModel();
            // 获取合盘报告商品
            $synastryReportGoods = (new Goods())->GoodsTypeInfo(17);

            foreach ($synastryReportGoods as $k => $v)
            {
                $goodType = (isset($v['good_type']) && $v['good_type'] === 17) ? 17 : 7;
                // 恋爱合盘报告解锁数量
                if ($goodType === 17)
                {
                    $unlockNum1 = $v['base_num'] + $orderModel->getTotalPrepaidOrder($goodType, $v['srid']);
                }
            }
        }


        /**
         * TODO 是否展示优惠券的弹窗
         * 仅在用户完成邀请，第一次点击进入合盘结果页
         */
        $isShowCouponTip = false;

        return $this->fetch($showType, [
            'rn' => $this->checkRuntimeEnvironment(),
            'index_url' => $this->domain . '/web/synastry/index2023?zhunle_not_show_nav=1&zhunle_nav_text_color=1',
            'oss' => $this->oss,
            'data' => $data,
            'total_score' => $score,
            'result' => $result,
            'height' => input('h/d', 0),
            'title' => '合盘结果',
            'show_type' => $params['show_type'],// 页面展示样式
            'is_show_coupon' => $isShowCouponTip && $app_type !== '' && $params['show_type'] == 3,
            'app_type' => $app_type,
            'share_title' => $shareTitle,
            'share_des' => $shareDes,
            'share_link' => $this->domain . '/web/synastry/get_with_score2023.html?id=' . $id . '&token=' . $token . '&zhunle_not_show_nav=1&zhunle_nav_text_color=1&share=1',
            'tips' => $tips,// 不显示完整版的时候，增加提示信息
            'unlockNum1' => $unlockNum1,
        ]);
    }
}
